home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Online / SpeakFreely / src / libdes / des.c < prev    next >
C/C++ Source or Header  |  2000-05-18  |  20KB  |  951 lines

  1. /* lib/des/des.c */
  2. /* Copyright (C) 1995 Eric Young (eay@mincom.oz.au)
  3.  * All rights reserved.
  4.  * 
  5.  * This file is part of an SSL implementation written
  6.  * by Eric Young (eay@mincom.oz.au).
  7.  * The implementation was written so as to conform with Netscapes SSL
  8.  * specification.  This library and applications are
  9.  * FREE FOR COMMERCIAL AND NON-COMMERCIAL USE
  10.  * as long as the following conditions are aheared to.
  11.  * 
  12.  * Copyright remains Eric Young's, and as such any Copyright notices in
  13.  * the code are not to be removed.  If this code is used in a product,
  14.  * Eric Young should be given attribution as the author of the parts used.
  15.  * This can be in the form of a textual message at program startup or
  16.  * in documentation (online or textual) provided with the package.
  17.  * 
  18.  * Redistribution and use in source and binary forms, with or without
  19.  * modification, are permitted provided that the following conditions
  20.  * are met:
  21.  * 1. Redistributions of source code must retain the copyright
  22.  *    notice, this list of conditions and the following disclaimer.
  23.  * 2. Redistributions in binary form must reproduce the above copyright
  24.  *    notice, this list of conditions and the following disclaimer in the
  25.  *    documentation and/or other materials provided with the distribution.
  26.  * 3. All advertising materials mentioning features or use of this software
  27.  *    must display the following acknowledgement:
  28.  *    This product includes software developed by Eric Young (eay@mincom.oz.au)
  29.  * 
  30.  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
  31.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  32.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  33.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  34.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  35.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  36.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  37.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  38.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  39.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  40.  * SUCH DAMAGE.
  41.  * 
  42.  * The licence and distribution terms for any publically available version or
  43.  * derivative of this code cannot be changed.  i.e. this code cannot simply be
  44.  * copied and put under another distribution licence
  45.  * [including the GNU Public Licence.]
  46.  */
  47.  
  48. #include <stdio.h>
  49. #include <stdlib.h>
  50. #ifndef MSDOS
  51. #include <unistd.h>
  52. #else
  53. #include <io.h>
  54. #define RAND
  55. #endif
  56.  
  57. #include <time.h>
  58. #include "version.h"
  59.  
  60. #ifdef VMS
  61. #include <types.h>
  62. #include <stat.h>
  63. #else
  64. #ifndef _IRIX
  65. #include <sys/types.h>
  66. #endif
  67. #include <sys/stat.h>
  68. #endif
  69. #if defined(NOCONST)
  70. #define const
  71. #endif
  72. #include "des.h"
  73.  
  74. #if defined(__STDC__) || defined(VMS) || defined(M_XENIX) || defined(MSDOS)
  75. #include <string.h>
  76. #endif
  77.  
  78. #ifdef RAND
  79. #define random rand
  80. #define srandom(s) srand(s)
  81. #endif
  82.  
  83. #ifdef PROTO
  84. void usage(void);
  85. void doencryption(void);
  86. int uufwrite(unsigned char *data, int size, unsigned int num, FILE *fp);
  87. void uufwriteEnd(FILE *fp);
  88. int uufread(unsigned char *out,int size,unsigned int num,FILE *fp);
  89. int uuencode(unsigned char *in,int num,unsigned char *out);
  90. int uudecode(unsigned char *in,int num,unsigned char *out);
  91. #else
  92. void usage();
  93. void doencryption();
  94. int uufwrite();
  95. void uufwriteEnd();
  96. int uufread();
  97. int uuencode();
  98. int uudecode();
  99. #endif
  100.  
  101. #ifdef VMS
  102. #define EXIT(a) exit(a&0x10000000)
  103. #else
  104. #define EXIT(a) exit(a)
  105. #endif
  106.  
  107. #define BUFSIZE (8*1024)
  108. #define VERIFY  1
  109. #define KEYSIZ    8
  110. #define KEYSIZB 1024 /* should hit tty line limit first :-) */
  111. char key[KEYSIZB+1];
  112. int do_encrypt,longk=0;
  113. FILE *DES_IN,*DES_OUT,*CKSUM_OUT;
  114. char uuname[200];
  115. unsigned char uubuf[50];
  116. int uubufnum;
  117. #define INUUBUFN    (45*100)
  118. #define OUTUUBUF    (65*100)
  119. unsigned char b[OUTUUBUF];
  120. unsigned char bb[300];
  121. des_cblock cksum={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
  122. char cksumname[200]="";
  123.  
  124. int vflag,cflag,eflag,dflag,kflag,bflag,fflag,sflag,uflag,flag3,hflag,error;
  125.  
  126. int main(argc, argv)
  127. int argc;
  128. char **argv;
  129.     {
  130.     int i;
  131.     struct stat ins,outs;
  132.     char *p;
  133.     char *in=NULL,*out=NULL;
  134.  
  135.     vflag=cflag=eflag=dflag=kflag=hflag=bflag=fflag=sflag=uflag=flag3=0;
  136.     error=0;
  137.     memset(key,0,sizeof(key));
  138.  
  139.     for (i=1; i<argc; i++)
  140.         {
  141.         p=argv[i];
  142.         if ((p[0] == '-') && (p[1] != '\0'))
  143.             {
  144.             p++;
  145.             while (*p)
  146.                 {
  147.                 switch (*(p++))
  148.                     {
  149.                 case '3':
  150.                     flag3=1;
  151.                     longk=1;
  152.                     break;
  153.                 case 'c':
  154.                     cflag=1;
  155.                     strncpy(cksumname,p,200);
  156.                     p+=strlen(cksumname);
  157.                     break;
  158.                 case 'C':
  159.                     cflag=1;
  160.                     longk=1;
  161.                     strncpy(cksumname,p,200);
  162.                     p+=strlen(cksumname);
  163.                     break;
  164.                 case 'e':
  165.                     eflag=1;
  166.                     break;
  167.                 case 'v':
  168.                     vflag=1;
  169.                     break;
  170.                 case 'E':
  171.                     eflag=1;
  172.                     longk=1;
  173.                     break;
  174.                 case 'd':
  175.                     dflag=1;
  176.                     break;
  177.                 case 'D':
  178.                     dflag=1;
  179.                     longk=1;
  180.                     break;
  181.                 case 'b':
  182.                     bflag=1;
  183.                     break;
  184.                 case 'f':
  185.                     fflag=1;
  186.                     break;
  187.                 case 's':
  188.                     sflag=1;
  189.                     break;
  190.                 case 'u':
  191.                     uflag=1;
  192.                     strncpy(uuname,p,200);
  193.                     p+=strlen(uuname);
  194.                     break;
  195.                 case 'h':
  196.                     hflag=1;
  197.                     break;
  198.                 case 'k':
  199.                     kflag=1;
  200.                     if ((i+1) == argc)
  201.                         {
  202.                         fputs("must have a key with the -k option\n",stderr);
  203.                         error=1;
  204.                         }
  205.                     else
  206.                         {
  207.                         int j;
  208.  
  209.                         i++;
  210.                         strncpy(key,argv[i],KEYSIZB);
  211.                         for (j=strlen(argv[i])-1; j>=0; j--)
  212.                             argv[i][j]='\0';
  213.                         }
  214.                     break;
  215.                 default:
  216.                     fprintf(stderr,"'%c' unknown flag\n",p[-1]);
  217.                     error=1;
  218.                     break;
  219.                     }
  220.                 }
  221.             }
  222.         else
  223.             {
  224.             if (in == NULL)
  225.                 in=argv[i];
  226.             else if (out == NULL)
  227.                 out=argv[i];
  228.             else
  229.                 error=1;
  230.             }
  231.         }
  232.     if (error) usage();
  233.     /* We either
  234.      * do checksum or
  235.      * do encrypt or
  236.      * do decrypt or
  237.      * do decrypt then ckecksum or
  238.      * do checksum then encrypt
  239.      */
  240.     if (((eflag+dflag) == 1) || cflag)
  241.         {
  242.         if (eflag) do_encrypt=DES_ENCRYPT;
  243.         if (dflag) do_encrypt=DES_DECRYPT;
  244.         }
  245.     else
  246.         {
  247.         if (vflag) 
  248.             {
  249. #ifndef _Windows            
  250.             fprintf(stderr,"des(1) built with %s\n",DES_version);
  251. #endif            
  252.             EXIT(1);
  253.             }
  254.         else usage();
  255.         }
  256.  
  257. #ifndef _Windows            
  258.     if (vflag) fprintf(stderr,"des(1) built with %s\n",DES_version);
  259. #endif            
  260.     if (    (in != NULL) &&
  261.         (out != NULL) &&
  262. #ifndef MSDOS
  263.         (stat(in,&ins) != -1) &&
  264.         (stat(out,&outs) != -1) &&
  265.         (ins.st_dev == outs.st_dev) &&
  266.         (ins.st_ino == outs.st_ino))
  267. #else /* MSDOS */
  268.         (strcmp(in,out) == 0))
  269. #endif
  270.             {
  271.             fputs("input and output file are the same\n",stderr);
  272.             EXIT(3);
  273.             }
  274.  
  275.     if (!kflag)
  276.         if (des_read_pw_string(key,KEYSIZB+1,"Enter key:",eflag?VERIFY:0))
  277.             {
  278.             fputs("password error\n",stderr);
  279.             EXIT(2);
  280.             }
  281.  
  282.     if (in == NULL)
  283.         DES_IN=stdin;
  284.     else if ((DES_IN=fopen(in,"r")) == NULL)
  285.         {
  286.         perror("opening input file");
  287.         EXIT(4);
  288.         }
  289.  
  290.     CKSUM_OUT=stdout;
  291.     if (out == NULL)
  292.         {
  293.         DES_OUT=stdout;
  294.         CKSUM_OUT=stderr;
  295.         }
  296.     else if ((DES_OUT=fopen(out,"w")) == NULL)
  297.         {
  298.         perror("opening output file");
  299.         EXIT(5);
  300.         }
  301.  
  302. #ifdef MSDOS
  303.     /* This should set the file to binary mode. */
  304.     {
  305. #include <fcntl.h>
  306.     if (!(uflag && dflag))
  307.         setmode(fileno(DES_IN),O_BINARY);
  308.     if (!(uflag && eflag))
  309.         setmode(fileno(DES_OUT),O_BINARY);
  310.     }
  311. #endif
  312.  
  313.     doencryption();
  314.     fclose(DES_IN);
  315.     fclose(DES_OUT);
  316.     EXIT(0);
  317.     }
  318.  
  319. void usage()
  320.     {
  321.     char **u;
  322.     static const char *Usage[]={
  323. "des <options> [input-file [output-file]]",
  324. "options:",
  325. "-v         : des(1) version number",
  326. "-e         : encrypt using sunOS compatible user key to DES key conversion.",
  327. "-E         : encrypt ",
  328. "-d         : decrypt using sunOS compatible user key to DES key conversion.",
  329. "-D         : decrypt ",
  330. "-c[ckname] : generate a cbc_cksum using sunOS compatible user key to",
  331. "             DES key conversion and output to ckname (stdout default,",
  332. "             stderr if data being output on stdout).  The checksum is",
  333. "             generated before encryption and after decryption if used",
  334. "             in conjunction with -[eEdD].",
  335. "-C[ckname] : generate a cbc_cksum as for -c but compatible with -[ED].",
  336. "-k key     : use key 'key'",
  337. "-h         : the key that is entered will be a hexidecimal number",
  338. "             that is used directly as the des key",
  339. "-u[uuname] : input file is uudecoded if -[dD] or output uuencoded data if -[eE]",
  340. "             (uuname is the filename to put in the uuencode header).",
  341. "-b         : encrypt using DES in ecb encryption mode, the defaut is cbc mode.",
  342. "-3         : encrypt using tripple DES encryption.  This uses 2 keys",
  343. "             generated from the input key.  If the input key is less",
  344. "             than 8 characters long, this is equivelent to normal",
  345. "             encryption.  Default is tripple cbc, -b makes it tripple ecb.",
  346. NULL
  347. };
  348.     for (u=(char **)Usage; *u; u++)
  349.         {
  350.         fputs(*u,stderr);
  351.         fputc('\n',stderr);
  352.         }
  353.  
  354.     EXIT(1);
  355.     }
  356.  
  357. void doencryption()
  358.     {
  359. #ifdef _LIBC
  360.     extern int srandom();
  361.     extern int random();
  362.     extern unsigned long time();
  363. #endif
  364.  
  365.     register int i;
  366.     des_key_schedule ks,ks2;
  367.     unsigned char iv[8],iv2[8];
  368.     char *p;
  369.     int num=0,j,k,l,rem,ll,len,last,ex=0;
  370.     des_cblock kk,k2;
  371.     FILE *O;
  372.     int Exit=0;
  373. #ifndef MSDOS
  374.     static unsigned char buf[BUFSIZE+8],obuf[BUFSIZE+8];
  375. #else
  376.     static unsigned char *buf=NULL,*obuf=NULL;
  377.  
  378.     if (buf == NULL)
  379.         {
  380.         if (    (( buf=(unsigned char *)malloc(BUFSIZE+8)) == NULL) ||
  381.             ((obuf=(unsigned char *)malloc(BUFSIZE+8)) == NULL))
  382.             {
  383.             fputs("Not enough memory\n",stderr);
  384.             Exit=10;
  385.             goto problems;
  386.             }
  387.         }
  388. #endif
  389.  
  390.     if (hflag)
  391.         {
  392.         j=(flag3?16:8);
  393.         p=key;
  394.         for (i=0; i<j; i++)
  395.             {
  396.             k=0;
  397.             if ((*p <= '9') && (*p >= '0'))
  398.                 k=(*p-'0')<<4;
  399.             else if ((*p <= 'f') && (*p >= 'a'))
  400.                 k=(*p-'a'+10)<<4;
  401.             else if ((*p <= 'F') && (*p >= 'A'))
  402.                 k=(*p-'A'+10)<<4;
  403.             else
  404.                 {
  405.                 fputs("Bad hex key\n",stderr);
  406.                 Exit=9;
  407.                 goto problems;
  408.                 }
  409.             p++;
  410.             if ((*p <= '9') && (*p >= '0'))
  411.                 k|=(*p-'0');
  412.             else if ((*p <= 'f') && (*p >= 'a'))
  413.                 k|=(*p-'a'+10);
  414.             else if ((*p <= 'F') && (*p >= 'A'))
  415.                 k|=(*p-'A'+10);
  416.             else
  417.                 {
  418.                 fputs("Bad hex key\n",stderr);
  419.                 Exit=9;
  420.                 goto problems;
  421.                 }
  422.             p++;
  423.             if (i < 8)
  424.                 kk[i]=k;
  425.             else
  426.                 k2[i-8]=k;
  427.             }
  428.         des_set_key((C_Block *)k2,ks2);
  429.         memset(k2,0,sizeof(k2));
  430.         }
  431.     else if (longk || flag3)
  432.         {
  433.         if (flag3)
  434.             {
  435.             des_string_to_2keys(key,(C_Block *)kk,(C_Block *)k2);
  436.             des_set_key((C_Block *)k2,ks2);
  437.             memset(k2,0,sizeof(k2));
  438.             }
  439.         else
  440.             des_string_to_key(key,(C_Block *)kk);
  441.         }
  442.     else
  443.         for (i=0; i<KEYSIZ; i++)
  444.             {
  445.             l=0;
  446.             k=key[i];
  447.             for (j=0; j<8; j++)
  448.                 {
  449.                 if (k&1) l++;
  450.                 k>>=1;
  451.                 }
  452.             if (l & 1)
  453.                 kk[i]=key[i]&0x7f;
  454.             else
  455.                 kk[i]=key[i]|0x80;
  456.             }
  457.  
  458.     des_set_key((C_Block *)kk,ks);
  459.     memset(key,0,sizeof(key));
  460.     memset(kk,0,sizeof(kk));
  461.     /* woops - A bug that does not showup under unix :-( */
  462.     memset(iv,0,sizeof(iv));
  463.     memset(iv2,0,sizeof(iv2));
  464.  
  465.     l=1;
  466.     rem=0;
  467.     /* first read */
  468.     if (eflag || (!dflag && cflag))
  469.         {
  470.         for (;;)
  471.             {
  472.             num=l=fread(&(buf[rem]),1,BUFSIZE,DES_IN);
  473.             l+=rem;
  474.             num+=rem;
  475.             if (l < 0)
  476.                 {
  477.                 perror("read error");
  478.                 Exit=6;
  479.                 goto problems;
  480.                 }
  481.  
  482.             rem=l%8;
  483.             len=l-rem;
  484.             if (feof(DES_IN))
  485.                 {
  486.                 srandom((unsigned int)time(NULL));
  487.                 for (i=7-rem; i>0; i--)
  488.                     buf[l++]=random()&0xff;
  489.                 buf[l++]=rem;
  490.                 ex=1;
  491.                 len+=rem;
  492.                 }
  493.             else
  494.                 l-=rem;
  495.  
  496.             if (cflag)
  497.                 {
  498.                 des_cbc_cksum((C_Block *)buf,(C_Block *)cksum,
  499.                     (long)len,ks,(C_Block *)cksum);
  500.                 if (!eflag)
  501.                     {
  502.                     if (feof(DES_IN)) break;
  503.                     else continue;
  504.                     }
  505.                 }
  506.  
  507.             if (bflag && !flag3)
  508.                 for (i=0; i<l; i+=8)
  509.                     des_ecb_encrypt(
  510.                         (des_cblock *)&(buf[i]),
  511.                         (des_cblock *)&(obuf[i]),
  512.                         ks,do_encrypt);
  513.             else if (flag3 && bflag)
  514.                 for (i=0; i<l; i+=8)
  515.                     des_ecb2_encrypt(
  516.                         (des_cblock *)&(buf[i]),
  517.                         (des_cblock *)&(obuf[i]),
  518.                         ks,ks2,do_encrypt);
  519.             else if (flag3 && !bflag)
  520.                 {
  521.                 char tmpbuf[8];
  522.  
  523.                 if (rem) memcpy(tmpbuf,&(buf[l]),
  524.                     (unsigned int)rem);
  525.                 des_3cbc_encrypt(
  526.                     (des_cblock *)buf,(des_cblock *)obuf,
  527.                     (long)l,ks,ks2,(des_cblock *)iv,
  528.                     (des_cblock *)iv2,do_encrypt);
  529.                 if (rem) memcpy(&(buf[l]),tmpbuf,
  530.                     (unsigned int)rem);
  531.                 }
  532.             else
  533.                 {
  534.                 des_cbc_encrypt(
  535.                     (des_cblock *)buf,(des_cblock *)obuf,
  536.                     (long)l,ks,(des_cblock *)iv,do_encrypt);
  537.                 if (l >= 8) memcpy(iv,&(obuf[l-8]),8);
  538.                 }
  539.             if (rem) memcpy(buf,&(buf[l]),(unsigned int)rem);
  540.  
  541.             i=0;
  542.             while (i < l)
  543.                 {
  544.                 if (uflag)
  545.                     j=uufwrite(obuf,1,(unsigned int)l-i,
  546.                         DES_OUT);
  547.                 else
  548.                     j=fwrite(obuf,1,(unsigned int)l-i,
  549.                         DES_OUT);
  550.                 if (j == -1)
  551.                     {
  552.                     perror("Write error");
  553.                     Exit=7;
  554.                     goto problems;
  555.                     }
  556.                 i+=j;
  557.                 }
  558.             if (feof(DES_IN))
  559.                 {
  560.                 if (uflag) uufwriteEnd(DES_OUT);
  561.                 break;
  562.                 }
  563.             }
  564.         }
  565.     else /* decrypt */
  566.         {
  567.         ex=1;
  568.         for (;;)
  569.             {
  570.             if (ex) {
  571.                 if (uflag)
  572.                     l=uufread(buf,1,BUFSIZE,DES_IN);
  573.                 else
  574.                     l=fread(buf,1,BUFSIZE,DES_IN);
  575.                 ex=0;
  576.                 rem=l%8;
  577.                 l-=rem;
  578.                 }
  579.             if (l < 0)
  580.                 {
  581.                 perror("read error");
  582.                 Exit=6;
  583.                 goto problems;
  584.                 }
  585.  
  586.             if (bflag && !flag3)
  587.                 for (i=0; i<l; i+=8)
  588.                     des_ecb_encrypt(
  589.                         (des_cblock *)&(buf[i]),
  590.                         (des_cblock *)&(obuf[i]),
  591.                         ks,do_encrypt);
  592.             else if (flag3 && bflag)
  593.                 for (i=0; i<l; i+=8)
  594.                     des_ecb2_encrypt(
  595.                         (des_cblock *)&(buf[i]),
  596.                         (des_cblock *)&(obuf[i]),
  597.                         ks,ks2,do_encrypt);
  598.             else if (flag3 && !bflag)
  599.                 {
  600.                 des_3cbc_encrypt(
  601.                     (des_cblock *)buf,(des_cblock *)obuf,
  602.                     (long)l,ks,ks2,(des_cblock *)iv,
  603.                     (des_cblock *)iv2,do_encrypt);
  604.                 }
  605.             else
  606.                 {
  607.                 des_cbc_encrypt(
  608.                     (des_cblock *)buf,(des_cblock *)obuf,
  609.                      (long)l,ks,(des_cblock *)iv,do_encrypt);
  610.                 if (l >= 8) memcpy(iv,&(buf[l-8]),8);
  611.                 }
  612.  
  613.             if (uflag)
  614.                 ll=uufread(&(buf[rem]),1,BUFSIZE,DES_IN);
  615.             else
  616.                 ll=fread(&(buf[rem]),1,BUFSIZE,DES_IN);
  617.             ll+=rem;
  618.             rem=ll%8;
  619.             ll-=rem;
  620.             if (feof(DES_IN) && (ll == 0))
  621.                 {
  622.                 last=obuf[l-1];
  623.  
  624.                 if ((last > 7) || (last < 0))
  625.                     {
  626.                     fputs("The file was not decrypted correctly.\n",
  627.                         stderr);
  628.                     /*Exit=8;
  629.                     goto problems;*/
  630.                     last=0;
  631.                     }
  632.                 l=l-8+last;
  633.                 }
  634.             i=0;
  635.             if (cflag) des_cbc_cksum((C_Block *)obuf,
  636.                 (C_Block *)cksum,(long)l/8*8,ks,
  637.                 (C_Block *)cksum);
  638.             while (i != l)
  639.                 {
  640.                 j=fwrite(obuf,1,(unsigned int)l-i,DES_OUT);
  641.                 if (j == -1)
  642.                     {
  643.                     perror("Write error");
  644.                     Exit=7;
  645.                     goto problems;
  646.                     }
  647.                 i+=j;
  648.                 }
  649.             l=ll;
  650.             if ((l == 0) && feof(DES_IN)) break;
  651.             }
  652.         }
  653.     if (cflag)
  654.         {
  655.         l=0;
  656.         if (cksumname[0] != '\0')
  657.             {
  658.             if ((O=fopen(cksumname,"w")) != NULL)
  659.                 {
  660.                 CKSUM_OUT=O;
  661.                 l=1;
  662.                 }
  663.             }
  664.         for (i=0; i<8; i++)
  665.             fprintf(CKSUM_OUT,"%02X",cksum[i]);
  666.         fprintf(CKSUM_OUT,"\n");
  667.         if (l) fclose(CKSUM_OUT);
  668.         }
  669. problems:
  670.     memset(buf,0,sizeof(buf));
  671.     memset(obuf,0,sizeof(obuf));
  672.     memset(ks,0,sizeof(ks));
  673.     memset(ks2,0,sizeof(ks2));
  674.     memset(iv,0,sizeof(iv));
  675.     memset(iv2,0,sizeof(iv2));
  676.     memset(kk,0,sizeof(kk));
  677.     memset(k2,0,sizeof(k2));
  678.     memset(uubuf,0,sizeof(uubuf));
  679.     memset(b,0,sizeof(b));
  680.     memset(bb,0,sizeof(bb));
  681.     memset(cksum,0,sizeof(cksum));
  682.     if (Exit) EXIT(Exit);
  683.     }
  684.  
  685. int uufwrite(data, size, num, fp)
  686. unsigned char *data;
  687. int size;
  688. unsigned int num;
  689. FILE *fp;
  690.       
  691.      /* We ignore this parameter but it should be > ~50 I believe */
  692.    
  693.     
  694.     {
  695.     int i,j,left,rem,ret=num;
  696.     static int start=1;
  697.  
  698.     if (start)
  699.         {
  700.         fprintf(fp,"begin 600 %s\n",
  701.             (uuname[0] == '\0')?"text.d":uuname);
  702.         start=0;
  703.         }
  704.  
  705.     if (uubufnum)
  706.         {
  707.         if (uubufnum+num < 45)
  708.             {
  709.             memcpy(&(uubuf[uubufnum]),data,(unsigned int)num);
  710.             uubufnum+=num;
  711.             return(num);
  712.             }
  713.         else
  714.             {
  715.             i=45-uubufnum;
  716.             memcpy(&(uubuf[uubufnum]),data,(unsigned int)i);
  717.             j=uuencode((unsigned char *)uubuf,45,b);
  718.             fwrite(b,1,(unsigned int)j,fp);
  719.             uubufnum=0;
  720.             data+=i;
  721.             num-=i;
  722.             }
  723.         }
  724.  
  725.     for (i=0; i<(num-INUUBUFN); i+=INUUBUFN)
  726.         {
  727.         j=uuencode(&(data[i]),INUUBUFN,b);
  728.         fwrite(b,1,(unsigned int)j,fp);
  729.         }
  730.     rem=(num-i)%45;
  731.     left=(num-i-rem);
  732.     if (left)
  733.         {
  734.         j=uuencode(&(data[i]),left,b);
  735.         fwrite(b,1,(unsigned int)j,fp);
  736.         i+=left;
  737.         }
  738.     if (i != num)
  739.         {
  740.         memcpy(uubuf,&(data[i]),(unsigned int)rem);
  741.         uubufnum=rem;
  742.         }
  743.     return(ret);
  744.     }
  745.  
  746. void uufwriteEnd(fp)
  747. FILE *fp;
  748.     {
  749.     int j;
  750.     static const char *end=" \nend\n";
  751.  
  752.     if (uubufnum != 0)
  753.         {
  754.         uubuf[uubufnum]='\0';
  755.         uubuf[uubufnum+1]='\0';
  756.         uubuf[uubufnum+2]='\0';
  757.         j=uuencode(uubuf,uubufnum,b);
  758.         fwrite(b,1,(unsigned int)j,fp);
  759.         }
  760.     fwrite(end,1,strlen(end),fp);
  761.     }
  762.  
  763. int uufread(out, size, num, fp)
  764. unsigned char *out;
  765. int size; /* should always be > ~ 60; I actually ignore this parameter :-) */
  766. unsigned int num;
  767. FILE *fp;
  768.     {
  769.     int i,j,tot;
  770.     static int done=0;
  771.     static int valid=0;
  772.     static int start=1;
  773.  
  774.     if (start)
  775.         {
  776.         for (;;)
  777.             {
  778.             b[0]='\0';
  779.             fgets((char *)b,300,fp);
  780.             if (b[0] == '\0')
  781.                 {
  782.                 fprintf(stderr,"no 'begin' found in uuencoded input\n");
  783.                 return(-1);
  784.                 }
  785.             if (strncmp((char *)b,"begin ",6) == 0) break;
  786.             }
  787.         start=0;
  788.         }
  789.     if (done) return(0);
  790.     tot=0;
  791.     if (valid)
  792.         {
  793.         memcpy(out,bb,(unsigned int)valid);
  794.         tot=valid;
  795.         valid=0;
  796.         }
  797.     for (;;)
  798.         {
  799.         b[0]='\0';
  800.         fgets((char *)b,300,fp);
  801.         if (b[0] == '\0') break;
  802.         i=strlen((char *)b);
  803.         if ((b[0] == 'e') && (b[1] == 'n') && (b[2] == 'd'))
  804.             {
  805.             done=1;
  806.             while (!feof(fp))
  807.                 {
  808.                 fgets((char *)b,300,fp);
  809.                 }
  810.             break;
  811.             }
  812.         i=uudecode(b,i,bb);
  813.         if (i < 0) break;
  814.         if ((i+tot+8) > num)
  815.             {
  816.             /* num to copy to make it a multiple of 8 */
  817.             j=(num/8*8)-tot-8;
  818.             memcpy(&(out[tot]),bb,(unsigned int)j);
  819.             tot+=j;
  820.             memcpy(bb,&(bb[j]),(unsigned int)i-j);
  821.             valid=i-j;
  822.             break;
  823.             }
  824.         memcpy(&(out[tot]),bb,(unsigned int)i);
  825.         tot+=i;
  826.         }
  827.     return(tot);
  828.     }
  829.  
  830. #define ccc2l(c,l)      (l =((unsigned long)(*((c)++)))<<16, \
  831.              l|=((unsigned long)(*((c)++)))<< 8, \
  832.               l|=((unsigned long)(*((c)++))))
  833.  
  834. #define l2ccc(l,c)      (*((c)++)=(unsigned char)(((l)>>16)&0xff), \
  835.                     *((c)++)=(unsigned char)(((l)>> 8)&0xff), \
  836.                     *((c)++)=(unsigned char)(((l)    )&0xff))
  837.  
  838.  
  839. int uuencode(in, num, out)
  840. unsigned char *in;
  841. int num;
  842. unsigned char *out;
  843.     {
  844.     int j,i,n,tot=0;
  845.     unsigned long l;
  846.     register unsigned char *p;
  847.     p=out;
  848.  
  849.     for (j=0; j<num; j+=45)
  850.         {
  851.         if (j+45 > num)
  852.             i=(num-j);
  853.         else    i=45;
  854.         *(p++)=i+' ';
  855.         for (n=0; n<i; n+=3)
  856.             {
  857.             ccc2l(in,l);
  858.             *(p++)=((l>>18)&0x3f)+' ';
  859.             *(p++)=((l>>12)&0x3f)+' ';
  860.             *(p++)=((l>> 6)&0x3f)+' ';
  861.             *(p++)=((l    )&0x3f)+' ';
  862.             tot+=4;
  863.             }
  864.         *(p++)='\n';
  865.         tot+=2;
  866.         }
  867.     *p='\0';
  868.     l=0;
  869.     return(tot);
  870.     }
  871.  
  872. int uudecode(in, num, out)
  873. unsigned char *in;
  874. int num;
  875. unsigned char *out;
  876.     {
  877.     int j,i,k;
  878.     unsigned int n=0,space=0;
  879.     unsigned long l;
  880.     unsigned long w,x,y,z;
  881.     unsigned int blank=(unsigned int)'\n'-' ';
  882.  
  883.     for (j=0; j<num; )
  884.         {
  885.         n= *(in++)-' ';
  886.         if (n == blank)
  887.             {
  888.             n=0;
  889.             in--;
  890.             }
  891.         if (n > 60)
  892.             {
  893.             fprintf(stderr,"uuencoded line length too long\n");
  894.             return(-1);
  895.             }
  896.         j++;
  897.  
  898.         for (i=0; i<n; j+=4,i+=3)
  899.             {
  900.             /* the following is for cases where spaces are
  901.              * removed from lines.
  902.              */
  903.             if (space)
  904.                 {
  905.                 w=x=y=z=0;
  906.                 }
  907.             else
  908.                 {
  909.                 w= *(in++)-' ';
  910.                 x= *(in++)-' ';
  911.                 y= *(in++)-' ';
  912.                 z= *(in++)-' ';
  913.                 }
  914.             if ((w > 63) || (x > 63) || (y > 63) || (z > 63))
  915.                 {
  916.                 k=0;
  917.                 if (w == blank) k=1;
  918.                 if (x == blank) k=2;
  919.                 if (y == blank) k=3;
  920.                 if (z == blank) k=4;
  921.                 space=1;
  922.                 switch (k) {
  923.                 case 1:    w=0; in--;
  924.                 case 2: x=0; in--;
  925.                 case 3: y=0; in--;
  926.                 case 4: z=0; in--;
  927.                     break;
  928.                 case 0:
  929.                     space=0;
  930.                     fprintf(stderr,"bad uuencoded data values\n");
  931.                     w=x=y=z=0;
  932.                     return(-1);
  933.                     break;
  934.                     }
  935.                 }
  936.             l=(w<<18)|(x<<12)|(y<< 6)|(z    );
  937.             l2ccc(l,out);
  938.             }
  939.         if (*(in++) != '\n')
  940.             {
  941.             fprintf(stderr,"missing nl in uuencoded line\n");
  942.             w=x=y=z=0;
  943.             return(-1);
  944.             }
  945.         j++;
  946.         }
  947.     *out='\0';
  948.     w=x=y=z=0;
  949.     return(n);
  950.     }
  951.